package com.yuews.strategy;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        //老生常谈的问题 if else 太多了如何优化？
        // 本文将使用策略模式去解决这个问题 以支付为例 会有 支付宝支付 微信支付 及其他支付方式
        //下面是优化前的代码
        String payType = "WeChatPay";
        if ("WeChatPay".equals(payType)){
            System.out.println("微信支付");
        } else if ("Alipay".equals(payType)) {
            System.out.println("支付宝支付");
        }//... 其他的支付方式
        //会发现代码中充满了if else 逻辑 只有几家支付厂商还好，越来越多那只能继续叠加 if else 使代码非常不美观
        System.out.println("--------------------------------------------------");
        //定义了一个Pay接口，Pay接口中包含pay方法与getPayType方法
        //使用反射获取继承Pay接口的实现类 然后通过getPayType去匹配支付方式
        Pay pay = findPay(payType);
        if (pay!=null){
            pay.pay();
        }else {
            System.out.println("没有该支付方式");
        }

    }

    /**
     * 根据支付方式名称查找对应的支付实现类
     * @param payType
     * @return
     */
    public static Pay findPay(String payType) {
        List<Pay> pays=scanPay();
        for (Pay pay : pays) {
            if (pay.getPayType().equals(payType)) {
                return pay;
            }
        }
        return null;
    }

    /**
     * 扫描继承了Pay接口的支付实现类
     * 接入了Spring也可以用自动注入的方式去扫描，就不需要如此复杂了
     * @return
     */
    private static List<Pay> scanPay() {
        try {
            String packageName = "com.yuews.strategy";
            List<Pay> implementations = new ArrayList<>();

            // 获取类加载器
            ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
            // 构造包路径 URL
            String path = packageName.replace('.', '/');
            URL resource = classLoader.getResource(path);
            if (resource == null) {
                throw new RuntimeException("无法找到资源: " + path);
            }

            // 转换为文件目录并列出所有 .class 文件
            File directory = new File(resource.getFile());
            if (!directory.exists()) {
                return implementations; // 如果不是文件夹，则返回空列表
            }

            File[] files = directory.listFiles((dir, name) -> name.endsWith(".class"));
            if (files == null) {
                return implementations;
            }

            for (File file : files) {
                // 提取类名（去掉 .class 后缀）
                String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
                // 加载类
                Class<?> clazz = classLoader.loadClass(className);

                // 检查该类是否实现了 Pay 接口且不是接口本身
                if (Pay.class.isAssignableFrom(clazz) && !clazz.isInterface()) {
                    // 创建实例并添加到结果集中
                    Pay instance = (Pay) clazz.getDeclaredConstructor().newInstance();
                    implementations.add(instance);
                }
            }
            return implementations;
        } catch (Exception e) {
            throw new RuntimeException("无法扫描支付实现类", e);
        }

    }

}
